# -*- coding: utf-8 -*-

from django.core.management.base import BaseCommand
from sys import stdin, stdout, stderr
import datetime
from nstat.traffic.models import UserProfile, BadLine, TrafficCategory, \
    TariffRule
from django.conf import settings
from os import environ
from django.db import transaction

DEBUG = settings.DEBUG

UNIT_ONLY = environ.has_key("UNIT_ONLY")
MAX_TIMESTAMP = int(environ.get("MAX_TIMESTAMP", 2000000000))
MIN_TIMESTAMP = int(environ.get("MIN_TIMESTAMP", 0))

print "Will parse only lines with %s < timestamp < %s\nUNIT_ONLY=%s" % (\
    datetime.datetime.fromtimestamp(int(MIN_TIMESTAMP)), \
    datetime.datetime.fromtimestamp(int(MAX_TIMESTAMP)), \
    UNIT_ONLY)

class Command(BaseCommand):
    help = "parses ulog-acctd data from stdin"

    @transaction.commit_on_success
    def handle(self, **options):
        """
        тут тоже вроде deadlock не дожен быть,
        т.к. хоть блокируем и все UserProfile, но одной командой, т.е. это операция атомарна (или нет?)
        """
        def debug(**args):
            if DEBUG:
                print dt
        count = 0
        results = {}
        users = {}
        for u in UserProfile.objects.select_for_update().all():
            users[u.ip] = u
        for line in stdin:
            count += 1
            if count % 10000 == 0:
                debug()
            try:
                timestamp, traffic_type, iface_in, iface_out, source_ip, \
                source_port, dest_ip, dest_port, protocol, bytes, packets = \
                    line.split(' ')
                dt = datetime.datetime.fromtimestamp(int(timestamp))
                if int(timestamp)<MIN_TIMESTAMP or int(timestamp)>MAX_TIMESTAMP:
                    continue
                traffic_type = int(traffic_type)
                source_port = int(source_port)
                dest_port = int(dest_port)
                protocol = int(protocol)
                bytes = int(bytes)
                packets = int(packets)
                if users.has_key(source_ip):
                    if users.has_key(dest_ip):
                        BadLine(label="l2l", line=line).save()
                        continue
                    else:
                        user = users[source_ip]
                        incoming = False
                else:
                    if users.has_key(dest_ip):
                        user = users[dest_ip]
                        incoming = True
                    else:
                        BadLine(label="e2e", line=line).save()
                        continue
                date = datetime.date(dt.year, dt.month, dt.day)
                hour = dt.hour
            except KeyboardInterrupt: return
            except:
                stderr.write(line+"\n")
                continue
            key = (date, hour, user.ip, traffic_type)
            results.setdefault(key, [0, 0])
            if incoming: results[key][0] += bytes
            else: results[key][1] += bytes
        bad = []
        for ((date, hour, ip, traffic_type), [incoming, outgoing]) in results.items():
            try: category = TrafficCategory.objects.get(id=traffic_type)
            except TrafficCategory.DoesNotExist:
                bad.append(("TrafficCategory.DoesNotExist", \
                    ((date, hour, ip, traffic_type), [incoming, outgoing])))
                continue
            user = users[ip]
            try:
                u = user.handle_traffic(date, hour, category, [incoming, outgoing], UNIT_ONLY)
                if DEBUG: print u
            except TariffRule.DoesNotExist:
                bad.append(("TariffRule.DoesNotExist", \
                    ((date, hour, user, category), [incoming, outgoing])))
                continue
        if bad:
            stderr.write('\n'.join(str(i) for i in bad)+"\n")
